﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

namespace BuildHelper
{
    class BuildHelper
    {
        private readonly string _sqlFileListFileName;
        private readonly string _outputFileName;
        private readonly string _bracketStartSymbol;
        private readonly string _bracketEndSymbol;
        private readonly bool _bracketStartsInclusive;
        private class BuildHelperException : Exception { public BuildHelperException(String msg) : base(msg) { } };

        private BuildHelper(string sqlFileListFileName, string outputFileName, string bracketSymbol, bool bracketStartsInclusive)
        {
            Console.WriteLine("Started BuildHelper");
            _sqlFileListFileName = sqlFileListFileName;
            _outputFileName = outputFileName;
            _bracketStartSymbol = bracketSymbol.Trim().ToLower() + "+";
            _bracketEndSymbol = bracketSymbol.Trim().ToLower() + "-";
            _bracketStartsInclusive = bracketStartsInclusive;
            Console.WriteLine("Parameters:" + _sqlFileListFileName + "," + _outputFileName);
        }

        static int Main(string[] args)
        {
            if(args.Length < 2)
            {
                System.Console.WriteLine("Usage: BuildHelper \"sqlFileListFileName\" \"outputFileName\" [\"bracketSymbol\" [\"+\"]]");
                System.Console.WriteLine("       If last parameter (\"+\") is supplied, the first lines of each file are included.");
                return -1;
            }
            var sqlFileListFileName = args[0];
            var outputFileName = args[1];
            var bracketSymbol = "";
            var bracketStartsInclusive = true;
            if(args.Length > 2)
            {
                bracketSymbol = args[2];
                bracketStartsInclusive = false;
                if(args.Length > 3)
                {
                    bracketStartsInclusive = (args[3] == "+");
                }
            }
            

            try
            {
                new BuildHelper(sqlFileListFileName, outputFileName, bracketSymbol, bracketStartsInclusive).Work();
                return 0;
            }
            catch (BuildHelperException buildHelperException)
            {
                ConsoleWriteError(buildHelperException.Message);
            }
            catch (Exception exception)
            {
                ConsoleWriteError(exception.Message);
            }
            return -1;
        }

        private static void ConsoleWriteError(string message)
        {
            var consoleColor = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(message);
            Console.ForegroundColor = consoleColor;
        }

        private void Work()
        {
            Console.WriteLine("Working...");
            FileStream outputFileStream;
            try
            {
                outputFileStream = System.IO.File.Create(_outputFileName);
            }
            catch
            {
                throw new BuildHelperException("Cannot create file: "+_outputFileName);
            }
            
            var outputFileStreamWriter = new StreamWriter(outputFileStream);

            try
            {
                foreach (var file in GetFileList(_sqlFileListFileName))
                {
                    PipeFile(outputFileStreamWriter, file);
                }
            }
            finally
            {
                outputFileStreamWriter.Close();
                outputFileStream.Close();
            }
            Console.WriteLine("BuildHelper Done.");
        }

        private void PipeFile(StreamWriter outputFileStreamWriter, string sqlFileFullPath)
        {
            Console.Write(sqlFileFullPath + "...");
            string fileContents;
            try
            {
                fileContents = ReadAllText(sqlFileFullPath);
            }
            catch
            {
                Console.WriteLine("Error");
                throw new BuildHelperException("Cannot read input file: " + sqlFileFullPath);
            }

//            outputFileStreamWriter.WriteLine(
//                "-- -----------------------------------------------------------------------------------------------------");
//            outputFileStreamWriter.WriteLine("-- -> " + sqlFileFullPath);
//            outputFileStreamWriter.WriteLine(
//                "-- -----------------------------------------------------------------------------------------------------");
            outputFileStreamWriter.WriteLine(fileContents);
            outputFileStreamWriter.WriteLine();
            outputFileStreamWriter.WriteLine("GO");
            outputFileStreamWriter.WriteLine();
            Console.WriteLine("OK");
        }

        private IEnumerable<string> GetFileList(string sqlFileListFileName)
        {
            if (IsFile(sqlFileListFileName))
            {
                try
                {
                    var path = Path.GetDirectoryName(sqlFileListFileName);
                    path = new System.IO.FileInfo(_sqlFileListFileName).DirectoryName;
                    return ReadInputFile(sqlFileListFileName).Where(file => (file.Trim() != "") && !(file.StartsWith("#"))).Select(file => path + "\\" + file.Trim()).ToArray();
                }
                catch
                {
                    throw new BuildHelperException("Cannot read list file: " + _sqlFileListFileName);
                }

            }
            else
            {
                var rootDir = Directory.GetCurrentDirectory();
                var pattern = Path.GetFileName(sqlFileListFileName);
                var relDir = Path.GetDirectoryName(sqlFileListFileName);
                if (relDir != null && pattern != null)
                {
                    var absPath = Path.GetFullPath(Path.Combine(rootDir, relDir));

                    return Directory.GetFiles(absPath, pattern, SearchOption.TopDirectoryOnly).OrderBy(file => file);
                }
                else
                {
                    throw new BuildHelperException("Invalid file list argument!");
                }
            }
        }

        private static bool IsFile(string sqlFileListFileName)
        {
            if(File.Exists(sqlFileListFileName))
            {
                var attr = File.GetAttributes(sqlFileListFileName);
                return (0 == (attr & FileAttributes.Directory));
            }
            return false;
        }

        private string ReadAllText(string sqlFileFullPath)
        {
            var text = new StringBuilder();

            var includeLine = _bracketStartsInclusive;

            foreach (var inputLine in ReadInputFile(sqlFileFullPath))
            {
                if(_bracketStartSymbol == inputLine.Trim().ToLower())
                {
                    includeLine = true;
                }
                else if(_bracketEndSymbol == inputLine.Trim().ToLower())
                {
                    includeLine = false;
                }
                else if(includeLine)
                {
                    text.AppendLine(inputLine);
                }
            }
            return text.ToString();
        }

        private IEnumerable<string> ReadInputFile(string fileName)
        {
            try
            {
                return System.IO.File.ReadAllLines(fileName);
            }
            catch
            {
                throw new BuildHelperException("Cannot read file: " + _sqlFileListFileName);
            }

        }
    }
}
